import AppDispatcher from '../AppDispatcher.js';
import * as ActionTypes from '../ActionTypes.js';
import {EventEmitter} from 'events';

const counterValues = {
	'First': 0,
	'Second': 10,
	'Third': 30,
}

const CHANGE_EVENT = 'changed';

//Object.assign()深拷贝的方法Object.assign() 只是一级属性复制，比浅拷贝多深拷贝了一层而已。用的时候，还是要注意这个问题的。
//他有三个参数，第一个参数不能为空
// // Cloning an object
// var obj = { a: 1 };
// var copy = Object.assign({}, obj);
// console.log(copy); // { a: 1 }
// // Merging objects
// var o1 = { a: 1 };
// var o2 = { b: 2 };
// var o3 = { c: 3 };

// var obj = Object.assign(o1, o2, o3);
// console.log(obj); // { a: 1, b: 2, c: 3 }
// console.log(o1);  // { a: 1, b: 2, c: 3 }, target object itself is changed.
//在这里是把CounterStore这个类复制了EventEmitter类中protoype的值//扩展了EventEmitter.prototype
//使得CounterStore成了EventEmitter对象，一个EventEmitter对象支持下列函数
//emit函数，可以广播一个特定事件，第一个参数是字符串类型的事件名称
// on函数，可以增加一个挂在这个EventEmitter对象特定事件上的处理函数，第一个参数是字符串类型的事件名称，第二个参数是处理函数
// removeListener函数，和on函数做的事情相反，删除挂在这个EventEmitter对象特定事件上的处理函数，和on函数一样，第一个参数是事件名称，第二个参数是处理函数，要注意，如果要调用removeListener函数就一定要保留对处理函数的引用
const CounterStore = Object.assign({}, EventEmitter.prototype, {

	//获取值
	getCounterValues: function () {
		return counterValues;
	},

	//
	emitChange: function () {
		this.emit(CHANGE_EVENT);
	},

	//
	addChangeListener: function (callback) {
		this.on(CHANGE_EVENT, callback);//第二个参数是处理函数
	},

	removeChangeListener: function (callback) {
		this.removeListener(CHANGE_EVENT, callback);//第二个参数是处理函数
	}
}) 

//上面的Store只有注册到Dispatcher实例上才能真正发挥作用，所以
//AppDispatcher有一个函数是register接受一个回调函数作为参数，返回值是一个token这个参数可以用于Store之间的同步，在这里用不到把他保存在CounterStore对象的dispatchToken字段上
//register接受的这个回调参数，这是Flux流程中最核心的部分，当通过register函数把一个回调函数注册到Dispatcher之后，所有派发给Dispatcher的action对象，都会传递到这个回调函数中来。
//比如通过Dispatcher派发一个动作
// AppDispatcher.dispatch({
// 	type: ActionTypes.INCREMENT,
// 	CounterCaption: 'First'
// })
//那么在CounterStore注册的回调函数就会被调用，唯一的一个参数就是那个actiion对象，回调函数要做的，就是根据action对象来决定如何来改变更新自己的状态
//作为一个普遍接受的传统，action对象必有一个type字段，类型是字符串，用于表示这个action对象是什么类型，上面的action对象中，type位‘INCREMENT’表示一个计数器的“加一”的动作，action还可以有其他字段，上面的就还有counterCapeion字段值位“First”,标识名字为'First'的计数器
//上面的动作含义就是‘名字为First的计数器要做加一的动作’
//根据不同的type，会有不同的操作所以注册的回调函数很自然的有一个模式，就是在函数体中是一串条件语句(if-else/switch),判断条件就是action的type字段
// 上面的例子中就根据type和counterCaption确定是哪个计数器，把counterValues上对应的字段做加一操作
//无论是做了什么操作，都要调用emitChange函数如果有调用者通过Counter.addChangeListner关注了CounterStore的状态变化，这个emitChange函数调用就会引发监听函数的执行
CounterStore.dispatchToken = AppDispatcher.register( (action) => {
	if (action.type === ActionTypes.INCREMENT) {
		counterValues[action.counterCapiton] ++;
		CounterStore.emitChange();
	} else if (action.type === ActionTypes.DECREMENT) {
		counterValues[action.counterCapiton] --;
		CounterStore.emitChange();
	}
} )

export default CounterStore;